package common;
import dfs.Inode;
import java.nio.ByteBuffer;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

import dfs.FileSystem;


public class Tester {

	
	public static void main(String[] args) {
		
		try {
			Object lock = new Object();
			FileSystem fileSystem = new FileSystem();
			fileSystem.init();
			Thread thread1 = new Thread(new Runnable1(fileSystem, lock));
			Thread thread2 = new Thread(new Runnable2(fileSystem, lock));
			Thread thread3 = new Thread(new Runnable3(fileSystem, lock));
			
			thread1.start();
			thread2.start();
			thread3.start();
			
			Thread.sleep(5000);
			
			thread1.join();
			thread2.join();
			thread3.join();
			System.out.println("calling sync");
			fileSystem.sync();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	public static class Runnable1 implements Runnable {
		public FileSystem fileSystem;
		public Object lock;
		public Runnable1(FileSystem fileSystem, Object lock) {
			this.fileSystem = fileSystem;
			this.lock = lock;
		}
		
		@Override
		public void run() {
			String string = "LONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFIL" +
					"ELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFI" +
					"LELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPE" +
					"RLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGF" +
					"ILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONG" +
					"FILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGF" +
					"ILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFILESUPERLONGFILELONGFILELONGFIL" +
					"ESUPERLONGFILE";
			
			byte[] data =string.getBytes();
			DFileID fileID = fileSystem.createDFile();
			fileSystem.write(fileID, data, 0, data.length);
			List<DFileID> ids = fileSystem.listAllDFiles();
			System.out.println("dfiles1 " + ids );
			// lock is to make sure file exists when it is being read, (not actually necessary)
			
			synchronized(lock) {
				DFileID id = ids.get(1);
				byte[] info = new byte[fileSystem.sizeDFile(id)];
				fileSystem.read(id, info, 0, fileSystem.sizeDFile(id));
				String result = new String(info);
				
				System.out.println("Reading file with id " + id.getID());
				System.out.println(result);
			}
		}
	}
	
	
	
	public static class Runnable2 implements Runnable {
		public FileSystem fileSystem;
		public Object lock;
		public Runnable2(FileSystem fileSystem, Object lock) {
			this.fileSystem = fileSystem;
			this.lock = lock;
		}
		
		@Override
		public void run() {
			String string = "short file";
			byte[] data = string.getBytes();
			DFileID fileID = fileSystem.createDFile();
			fileSystem.write(fileID, data, 0, data.length);
			List<DFileID> ids = fileSystem.listAllDFiles();
			System.out.println("dfiles2 "+ ids);
			
			for(DFileID id: ids) {
				byte[] info = new byte[fileSystem.sizeDFile(id)];
				fileSystem.read(id, info, 0, fileSystem.sizeDFile(id));
				String result = new String(info);
				
				System.out.println("Reading file with id " +id.getID());
				System.out.println(result);
				return;
			}
		}
	}
	
	public static class Runnable3 implements Runnable {
		public FileSystem fileSystem;
		public Object lock;
		public Runnable3(FileSystem fileSystem, Object lock) {
			this.fileSystem = fileSystem;
			this.lock = lock;
		}
		
		@Override
		public void run() {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			synchronized(lock){
				if (fileSystem.listAllDFiles().contains(new DFileID(1))){
					fileSystem.destroyDFile(new DFileID(1));
				}
			}
		}
	
	
		
		/***
		DFileID id = new DFileID(1);
		Inode node = new Inode(id);
		Object o = (Object) node;
		byte[] byteArray = null;
		try{
			byteArray = Serializer.serialize(o);
		} catch(IOException e){
			e.printStackTrace();
		}
		
		System.out.println("The length of the array is " +byteArray.length);
		***/
	}
}
